/**
 * @file utils.c
 * @brief 工具函数实现
 */

#include "action_camera.h"
#include <stdarg.h>

// 函数前向声明
void check_system_health(void);
void update_system_statistics(void);
void check_thread_health(void);

/**
 * @brief 获取系统时间戳
 * @return 微秒级时间戳
 */
uint64_t get_system_timestamp(void) {
    struct timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);
    return (uint64_t)ts.tv_sec * 1000000ULL + ts.tv_nsec / 1000;
}

/**
 * @brief 更新线程心跳
 * @param thread_id 线程ID
 */
void update_thread_heartbeat(thread_id_t thread_id) {
    if (thread_id >= 0 && thread_id < MAX_THREADS) {
        g_camera_system.threads[thread_id].last_heartbeat = get_system_timestamp();
    }
}

/**
 * @brief 日志输出函数
 * @param level 日志级别
 * @param format 格式字符串
 * @param ... 可变参数
 */
void log_message(const char* level, const char* format, ...) {
    pthread_mutex_lock(&g_camera_system.sync.log_mutex);
    
    // 获取当前时间
    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);
    
    struct tm* tm_info = localtime(&ts.tv_sec);
    
    // 输出时间戳和日志级别
    printf("[%04d-%02d-%02d %02d:%02d:%02d.%03ld] [%s] ",
           tm_info->tm_year + 1900,
           tm_info->tm_mon + 1,
           tm_info->tm_mday,
           tm_info->tm_hour,
           tm_info->tm_min,
           tm_info->tm_sec,
           ts.tv_nsec / 1000000,
           level);
    
    // 输出格式化消息
    va_list args;
    va_start(args, format);
    vprintf(format, args);
    va_end(args);
    
    printf("\n");
    fflush(stdout);
    
    pthread_mutex_unlock(&g_camera_system.sync.log_mutex);
}

/**
 * @brief 设置线程优先级
 * @param thread 线程句柄
 * @param priority 优先级
 * @return 0成功，-1失败
 */
int set_thread_priority(pthread_t thread, int priority) {
    struct sched_param param;
    param.sched_priority = priority;
    
    int policy = (priority > 0) ? SCHED_FIFO : SCHED_OTHER;
    
    int ret = pthread_setschedparam(thread, policy, &param);
    if (ret != 0) {
        LOG_WARN("Failed to set thread priority: %s", strerror(ret));
        return -1;
    }
    
    return 0;
}

/**
 * @brief 设置线程CPU亲和性
 * @param thread 线程句柄
 * @param cpu_id CPU核心ID
 * @return 0成功，-1失败
 */
int set_thread_affinity(pthread_t thread, int cpu_id) {
#ifdef __linux__
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
    CPU_SET(cpu_id, &cpuset);
    
    int ret = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
    if (ret != 0) {
        LOG_WARN("Failed to set CPU affinity: %s", strerror(ret));
        return -1;
    }
    
    LOG_DEBUG("Thread affinity set to CPU %d", cpu_id);
#else
    LOG_DEBUG("CPU affinity not supported on this platform");
#endif
    
    return 0;
}

/**
 * @brief 系统监控线程主函数
 * @param arg 线程参数
 * @return NULL
 */
void* system_monitor_thread(void* arg) {
    thread_id_t* tid = (thread_id_t*)arg;
    message_t msg;
    uint32_t monitor_cycle = 0;
    
    // 验证线程ID的有效性
    if (!tid || *tid >= MAX_THREADS) {
        printf("[ERROR] Monitor thread: Invalid thread ID pointer or value: tid=%p, value=%u\n", 
               (void*)tid, tid ? (unsigned)*tid : 999);
        return NULL;
    }
    
    printf("[DEBUG] Monitor thread started with valid ID: %u (pointer=%p)\n", (unsigned)*tid, (void*)tid);
    
    LOG_INFO("System monitor thread started", 0);
    atomic_fetch_add(&g_camera_system.sync.active_threads, 1);
    
    while (atomic_load(&g_camera_system.sync.system_running)) {
        update_thread_heartbeat(*tid);
        
        // 检查消息
        if (message_queue_receive(&g_camera_system.message_queues[*tid], &msg, 0) == 0) {
            if (msg.type == MSG_SHUTDOWN) {
                LOG_INFO("Monitor thread received shutdown message", 0);
                break;
            }
        }
        
        monitor_cycle++;
        
        // 每5秒执行一次系统检查
        if (monitor_cycle % 50 == 0) {
            check_system_health();
            update_system_statistics();
            check_thread_health();
        }
        
        // 每秒更新基本统计
        if (monitor_cycle % 10 == 0) {
            atomic_store(&g_camera_system.sync.system_timestamp, get_system_timestamp());
        }
        
        usleep(100000); // 100ms监控周期
    }
    
    LOG_INFO("System monitor thread exiting", 0);
    atomic_fetch_sub(&g_camera_system.sync.active_threads, 1);
    g_camera_system.threads[*tid].status = THREAD_TERMINATED;
    
    return NULL;
}

/**
 * @brief 检查系统健康状态
 */
void check_system_health(void) {
    // 模拟系统健康检查
    g_camera_system.stats.cpu_usage = 45 + (rand() % 20); // 45-65%
    g_camera_system.stats.memory_usage = 60 + (rand() % 20); // 60-80%
    g_camera_system.stats.temperature = 40 + (rand() % 15); // 40-55℃
    // 模拟电池消耗 - 确保计算结果不会导致无符号整数溢出
    uint64_t timestamp_seconds = get_system_timestamp() / 1000000;
    if (timestamp_seconds / 10 < 100) {
        g_camera_system.stats.battery_level = 100 - (timestamp_seconds / 10);
    } else {
        g_camera_system.stats.battery_level = 0; // 电池电量耗尽
    }
    
    // 检查异常状态
    if (g_camera_system.stats.temperature > 70) {
        LOG_WARN("High temperature detected: %u°C", g_camera_system.stats.temperature);
    }
    
    if (g_camera_system.stats.battery_level < 10) {
        LOG_WARN("Low battery: %u%%", g_camera_system.stats.battery_level);
    }
    
    if (g_camera_system.stats.memory_usage > 90) {
        LOG_WARN("High memory usage: %u%%", g_camera_system.stats.memory_usage);
    }
}

/**
 * @brief 更新系统统计信息
 */
void update_system_statistics(void) {
    pthread_mutex_lock(&g_camera_system.sync.stats_mutex);
    
    LOG_INFO("=== System Statistics ===", 0);
    LOG_INFO("Uptime: %lu seconds", 
             (get_system_timestamp() - g_camera_system.start_time) / 1000000);
    LOG_INFO("Frames: captured=%lu, encoded=%lu, dropped=%lu",
             g_camera_system.stats.frames_captured,
             g_camera_system.stats.frames_encoded,
             g_camera_system.stats.frames_dropped);
    LOG_INFO("Data written: %lu MB",
             g_camera_system.stats.bytes_written / (1024 * 1024));
    LOG_INFO("CPU: %u%%, Memory: %u%%, Temp: %u°C, Battery: %u%%",
             g_camera_system.stats.cpu_usage,
             g_camera_system.stats.memory_usage,
             g_camera_system.stats.temperature,
             g_camera_system.stats.battery_level);
    LOG_INFO("Active threads: %d", atomic_load(&g_camera_system.sync.active_threads));
    LOG_INFO("========================", 0);
    
    pthread_mutex_unlock(&g_camera_system.sync.stats_mutex);
}

/**
 * @brief 检查线程健康状态
 */
void check_thread_health(void) {
    uint64_t current_time = get_system_timestamp();
    
    for (int i = 1; i < MAX_THREADS; i++) {
        if (!g_camera_system.threads[i].enabled) {
            continue;
        }
        
        thread_monitor_t* monitor = &g_camera_system.threads[i];
        
        if (monitor->status == THREAD_RUNNING) {
            uint64_t idle_time = current_time - monitor->last_heartbeat;
            
            if (idle_time > THREAD_TIMEOUT) {
                LOG_ERROR("Thread %s timeout (idle: %lu ms)", 
                         monitor->thread_name, idle_time / 1000);
                
                monitor->error_count++;
                
                if (monitor->error_count >= 3) {
                    LOG_ERROR("Thread %s failed multiple times, marking as error", 
                             monitor->thread_name);
                    monitor->status = THREAD_ERROR;
                }
            }
        }
    }
}